package controllers;

import play.*;
import play.mvc.*;

import java.util.*;

import org.apache.commons.mail.EmailException;

import models.*;

@With(Secure.class)
// this class is used for the login, Doaa El-Hawary
public class Ideas extends Controller {

	public static void index() {
		render();
	}

	/**
	 * increments user's pointCounter when he posts idea
	 * 
	 * @author Caroline Tawfik
	 * @version 2011.0501
	 * @category C3S11

	 * @params userId: the ID of the user who posted the idea to increment his
	 *         pointCounter
	 * @return void
	 */
	public static void incrementIdeaCounter() {
		String username = session.get("username");
		User user = (User) User.find("byUsername", username).fetch().get(0);
		user.setPointCounter(user.getPointCounter() + 1);
		user.save();
	}

	public static void viewIdeasInTopic(long topicID) {

		Topic topic = Topic.findById(topicID);
		List ideas = new LinkedList();
		ideas = topic.getIdeas();
		render(ideas);
	}

	public static void viewIdeasInOrganization(long orgID) {

		Organization organization = Organization.findById(orgID);
		List ideas = new LinkedList();
		ideas = organization.getIdeas();
		render(ideas);
	}

	public static void viewIdeasInEntity(long entityID) {

		Eentity entity = Eentity.findById(entityID);
		List ideas = new LinkedList();
		ideas = entity.getIdeas();
		render(ideas);
	}

	
	/**
	 * views all non-draft ideas
	 * 
	 * @author Arwa Ismail
	 * @version 2010.0429
	 * @category C4S10
	 * @return void
	 */

	
	public static void viewAllIdeas() {
		List ideas = Idea.findAll();
		List<Idea> shownIdeas = new LinkedList<Idea>();
		for (int i = 0; i < ideas.size(); i++) {
			Idea id = (Idea) ideas.get(i);
			if (!(id.isDraft()))
				shownIdeas.add(id);

		}
		render(shownIdeas);
	}

	/**
	 * calls show.html in Ideas folder which renders based on the Idea id for
	 * instance a user would click on a link surrounded with <a
	 * href="@Ideas.show(topic.id)"></a> the method then check a couple of
	 * things before rendering
	 * 
	 * @author Amr Draz
	 * @version 2011.05.02
	 * @category C4S14
	 * @param id
	 *            : id of the topic that is to be shown
	 * @return none
	 */

	public static void show(long id) {

		Idea idea = Idea.findById(id);
		// / Draz's check for org privacy
		String username = Security.connected();
		User user = User.findByUsername(username);
		if (idea.getOrganization().isPrivate()
				&& !(idea.getOrganization().isMember(user)))
			render("errors/503.html");
		// end draz part

		render(idea, user);
	}

	/**
	 * Changes the value of boolean isDraft to true.
	 * 
	 * @author karim khalaf
	 * @version 2011.0205
	 * @category C3S10
	 * @parameter String title: of the idea 
	 *             String ideaDetail : of the idea, its title . 
	 *             Organization : that the idea belongs to
	 *            
	 * @return  void
	 */

	public static void saveAsDraft(String title, String ideaDetail,
			Organization organization) {

		String username = Security.connected();
		User user = User.findByUsername(username);
		LinkedList<User> creators = new LinkedList();
		creators.add(user);

		Idea idea = new Idea(title, ideaDetail, true, organization, creators);
		idea.save();
		System.out.println(idea.toString());
		

	}
	
	

	/**
	 * Changes the value of boolean isDraft to true.
	 * 
	 * @author karim khalaf
	 * @version 2011.0205
	 * @category C3S10
	 * @parameter String title: of the idea 
	 *             String ideaDetail : of the idea, its title . 
	 *             Topic : that the idea belongs to
	 *            
	 * @return  void
	 */

	public static void saveAsDraft(String title, String ideaDetail, Topic topic) {

		String username = Security.connected();
		User user = User.findByUsername(username);
		LinkedList<User> creators = new LinkedList();
		creators.add(user);

		Idea idea = new Idea(title, ideaDetail, true, topic, creators);
		idea.save();
		System.out.println(idea.toString());
	

	}

	  

	/**
	 * Changes the value of boolean isDraft to true.
	 * 
	 * @author karim khalaf
	 * @version 2011.0205
	 * @category C3S10
	 * @parameter String title: of the idea 
	 *             String ideaDetail : of the idea, its title . 
	 *             Eentity : that the idea belongs to
	 *            
	 * @return  void
	 */
	public static void saveAsDraft(String title, String ideaDetail,
			Eentity entity) {

		String username = Security.connected();
		User user = User.findByUsername(username);
		LinkedList<User> creators = new LinkedList();
		creators.add(user);

		Idea idea = new Idea(title, ideaDetail, true, entity, creators);
		idea.save();
		System.out.println(idea.toString());
		

	}

	/**
	 * Checks if idea belongs to user
	 * 
	 * @author karim khalaf
	 * @version 2010.0424
	 * @category C3 helper method
	 * @parameter Idea: to be check if belongs to user User : to check if he is
	 *            the owner og the given idea.
	 * @return Boolean: true if idea belongs to user.
	 */

	public static boolean ideaBelongsToUser(User user, Idea idea) {
		for (int i = 0; i < user.getIdeaList().size(); i++) {
			if (idea == user.getIdeaList().get(i))
				return true;

		}
		return false;

	}

 	/**
	 * Given two ideas, this method merges them either by deleting one and
	 * keeping the other or deleting both and creating a third one that is a
	 * combination of both
	 * 
	 * @author Nader Alexan
	 * @version 2010.0425
	 * @category C4S15
	 * @parameter long ideaOneID (The id of the first idea), long IdeaTwoID (The id of the second idea)
	 * @return
	 */

	public static void duplicate(long ideaOneID, long ideaTwoID, int choice) {
		Idea ideaOne = Idea.findById(ideaOneID);
		Idea ideaTwo = Idea.findById(ideaTwoID);
		long chosenID = 0;
		if (ideaOne == null || ideaTwo == null || (choice != 1 && choice != 2))
			render(chosenID);
		if (ideaOne.getOrganization() != null
				&& ideaTwo.getOrganization() != null)
			if (!ideaOne.getOrganization().equals(ideaTwo.getOrganization())
					|| !ideaOne.getEntity().equals(ideaTwo.getEntity())
					|| ideaOne.getTopic().equals(ideaTwo.getTopic()))
				render(chosenID);
		Idea chosen, toBeDeleted;

		// Choice 1 or 2 means that one idea will be deleted and the other will
		// be modified accordingly. The number in Choice resembles which Idea
		// will
		// be left
		chosen = (choice == 1) ? ideaOne : ideaTwo;
		toBeDeleted = (choice == 1) ? ideaTwo : ideaOne;
		chosen.setRating((ideaOne.getRating() + ideaTwo.getRating()) / 2);
		chosen.setDraft(ideaOne.isDraft() && ideaTwo.isDraft());
		chosen.setActivityStatus(ideaOne.isActivityStatus()
				&& ideaTwo.isActivityStatus());
		chosen.setExecutionStatus(ideaOne.isExecutionStatus()
				|| ideaTwo.isExecutionStatus());

		// for (int i = 0; i < toBeDeleted.getTags().size(); i++) {
		// Tag currentTag = toBeDeleted.getTags().get(i);
		// if (!chosen.getTags().contains(currentTag))
		// chosen.getTags().add(currentTag);
		// }
		for (int i = 0; i < toBeDeleted.getTags().size(); i++) {
			User currentIdeaFollower = toBeDeleted.getIdeaFollowers().get(i);
			if (!chosen.getIdeaFollowers().contains(currentIdeaFollower))
				chosen.getIdeaFollowers().add(currentIdeaFollower);
		}
		chosenID = chosen.getId();
		// toBeDeleted.delete();
		render(chosenID);
	}

	/**
	 * HELPER METHODS
	 * renders topic/entity/organization by giving their IDs
	 * @author Caroline Tawfik
	 * @version 2010.0505
	 * @category C3S2 - helper methods
	 * @parameter IDs
	 * @return void
	 * @throws EmailException
	 */
	public static void createIdeaInEntity(long entityId) {
		Eentity entity = Eentity.findById(entityId);

		render(entity);
	}

	public static void createIdeaInOrganization(long organizationId) {

		System.out.println(organizationId + "inside createorg");

		Organization organization = Organization.findById(organizationId);

		System.out.println(organization.getName());
		render(organization);
	}

	public static void createIdeaInTopic(long topicId) {
		Topic topic = Topic.findById(topicId);

		render(topic);
	}
	/**
	 * checks whether user can post idea to topic and posts the idea
	 * 
	 * 
	 * @author Caroline Tawfik
	 * @version 2010.0501
	 * @category C3S2
	 * @parameter String title,String ideaDetail, long topicId:the
	 *            topic the user posts the idea on (parameters of Idea); long
	 *            boolean saveAsDraft: to check if it's saved as draft or not
	 * @return void
	 * @throws EmailException
	 */
	public static boolean postIdeaInTopic(String title, String ideaDetail,
			boolean saveAsDraft, long topicId) throws EmailException {

		String username = session.get("username");
		User user = (User) User.find("byUsername", username).fetch().get(0);
		Topic topic = Topic.findById(topicId);
		boolean flag = false;
		// the check for user

		if (saveAsDraft) {
			saveAsDraft(title, ideaDetail, topic);
			return false;

		}

		// karim part

		if (saveAsDraft) {
			// saveAsDraft(title, ideaDetail,topic);
			return false;

		}

		// karim part

		String x;

		if (!(ideaDetail.equals(null) && title.equals(null))) {
			if (topic.getStatus().equals("closed")) {
				x = "Sorry,Topic closed";
				render(x);
				return true;
			}
			if (topic.getEntity().getAllUsersInEntity().contains(user)) {
				// if(topic.getOrganization().getAllUsersInOrg().contains(user))
				if (topic.getIdeas().contains(title)) {
					x = "Sorry there is another idea with this title already.";
					render(x);
					return true;
				}

				LinkedList<User> creators = new LinkedList<User>();
				creators.add(user);
				Idea idea = new Idea(title, ideaDetail, false, topic, creators);
				idea.save();
				//user.getIdeaList().add(idea);
				user.save();
				flag = true;
				incrementIdeaCounter();
				int length = topic.getFollowers().size();
				long[] toBeNotified = new long[length];
				for (int i = 0; i < topic.getFollowers().size(); i++) {
					toBeNotified[i] = topic.getFollowers().get(i).getId();
				}
				Notifications.notifyMany(user.getId(),
						toBeNotified, // author : mohamed elshikh
						"A new  Idea is Posted on ",
						"the topic " + topic.getTitle());
				x = title + "\n" + ideaDetail;
				render(title, ideaDetail, flag, x,topicId);

			} else {
				x = "Sorry you're not a member of this entity";
				render(x);
				return true;
			}
		} else {
			x = "Please enter a title and detail.";
			render(x);
			return true;
		}
		
		return true;

	}

	/**
	 * checks whether user can post idea to organization and posts the idea if
	 * yes
	 * 
	 * 
	 * @author Caroline Tawfik
	 * @version 2010.05.01
	 * @category C3S2
	 * @parameter String title,String ideaDetail,organizationId (parameters
	 *            of Idea); boolean saveAsDraft
	 * @return boolean: returns true if the user is allowed to post ideas on
	 *         this organization and idea has been posted successfully and
	 *         counter will be incremented
	 */

	public static boolean postIdeaInOrganization(String title,
			String ideaDetail, boolean saveAsDraft, long organizationId) {

		String username = session.get("username");
		User user = (User) User.find("byUsername", username).fetch().get(0);
		Organization org = Organization.findById(organizationId);
		boolean flag = false;

		if (saveAsDraft) {
			saveAsDraft(title, ideaDetail, org);
			return false;
		}// karim part

		if (saveAsDraft) {
			saveAsDraft(title, ideaDetail, org);
			return false;
		}// karim part
		String x = "";

		// the check for user
		if (!(ideaDetail.equals(null) && title.equals(null))) {
			if (org.getAllUsersInOrganization().contains(user)) {
				if (org.getIdeas().contains(title)) {
					x = "Sorry there exists another idea with this title";
					render(x);
					return true;
				}

				LinkedList<User> creators = new LinkedList<User>();
				creators.add(user);
				Idea idea = new Idea(title, ideaDetail, false, org, creators);
				idea.save();
			//	user.getIdeaList().add(idea);
				user.save();
				flag = true;
				incrementIdeaCounter();
				x = title + "\n" + ideaDetail;
				render(title, ideaDetail, flag, x,organizationId);
			} else {
				x = "You're not a member of this organization";
				render(x);
				return true;
			}
		} else {
			x = "Please enter a title and detail.";
			render(x);
			return true;
		}
		
		return true;

	}

	/**
	 * checks whether user can post idea to entity and then posts the idea
	 * 
	 * 
	 * @author Caroline Tawfik
	 * @version 2010.0430
	 * @category C3S2
	 * @parameter String title,String ideaDetail, long entityId
	 *            (parameters of Idea); boolean saveAsDraft
	 * @return boolean: returns true if the user is allowed to post ideas on
	 *         this topic/entity/organization and idea has been posted
	 *         successfully and counter will be incremented
	 */

	public static boolean postIdeaInEntity(String title, String ideaDetail,
			long entityId, boolean saveAsDraft) {
		String username = session.get("username");
		User user = (User) User.find("byUsername", username).fetch().get(0);
		Eentity ent = Eentity.findById(entityId);

		if (saveAsDraft) {
			saveAsDraft(title, ideaDetail, ent);
			return false;
		}// karim part

		if (saveAsDraft) {
			saveAsDraft(title, ideaDetail, ent);
			return false;
		}// karim part

		String x = "";

		boolean flag = false;
		// the check for user
		if (!(ideaDetail.equals(null) && title.equals(null))) {
			if (ent.getAllUsersInEntity().contains(user)) {
				if (ent.getIdeas().contains(title)) {
					x = "Sorry there exists an idea with this title already";
					render(x);
					return true;

				}
				LinkedList<User> creators = new LinkedList<User>();
				creators.add(user);
				Idea idea = new Idea(title, ideaDetail, false, ent, creators);
				idea.save();
			//	user.getIdeaList().add(idea);
				user.save();
				flag = true;
				incrementIdeaCounter();
				x = title + "\n" + ideaDetail;
				render(title, ideaDetail, flag, x,entityId);
				System.out.println("posted");
				return true;
			} else {
				x = "Sorry you cannot post on this entity since you're not a member of it";
				render(x);
				return true;
			}
			
			
		} else {
			x = "Please enter a title and detail";
			render(x);
			return true;
		}

	}



	 /**
		 * if the idea is already spammed it notifies the user of that and if not it sends notification 
		 * 
		 * @author Nora zakhary
		 * @version 2011.0504
		 * @category C3S7
		 * @param long id
		 * @return void
		 */

    public static void toSpamIdea(long id) throws EmailException{
    	Idea i = Idea.findById(id);
        boolean notSpammed;
    	
    	if(i.isSpam()){
    		notSpammed=false;
    	}
    	else{
    	i.setSpam(true);
    	notSpammed= true;
    	i.save();
    	Users.notifySpammedIdea(id);
    	
    	}
     render(id,notSpammed);
    }

	/**
	 * Sorts a List of ideas according to the highest votes or most viewed
	 * 
	 * @author Nader Alexan
	 * @version 2011.0501
	 * @category C4S11
	 * @param List
	 *            <Long> ideasID (list of ideas id's to be sorted), boolean
	 *            views (if false then sort by votes) boolean ascending (if
	 *            false then sort descendingly)
	 * @return void
	 */
	 

	public static void sort(List<Long> ideasID, boolean views, boolean ascending) {
		for (int i = 0; i < ideasID.size() - 1; i++)
			for (int j = 0; j < ideasID.size() - 1; j++) {
				float current, next;
				current = (Float) ((views) ? ((Idea) Idea.findById(ideasID
						.get(j))).getViews() : ((Idea) Idea.findById(ideasID
						.get(j))).getAverageRating());
				next = (Float) ((views) ? ((Idea) Idea.findById(ideasID
						.get(j + 1))).getViews() : ((Idea) Idea
						.findById(ideasID.get(j))).getAverageRating());
				if ((ascending) ? current > next : current < next)
					ideasID.add(j, ideasID.remove(j + 1));
			}
		render(ideasID);
	}

	/**
	 * Simply renders an idea to the view
	 * 
	 * @author Nader Alexan
	 * @version 2011.0501
	 * @param idea
	 */
	// Edited the method to pass the idea Id and the organization Id of
	// that idea Author : Aly Mostafa
	public static void viewIdea(long id) {
		// long id = idea.getId();
		Idea idea = Idea.findById(id);
		long belonger = idea.getOrganization().getId();
		String var = "Organization";
		if (idea.getTopic() != null) {
			belonger = idea.getTopic().id;
			var = "topic";

		} else if (idea.getEntity() != null) {
			belonger = idea.getEntity().id;
			var = "entity";

		}
		render(idea, id, belonger, var);

	}

	/**
	 * renders the list of the rest of the ideas in the same organization/entity/topic  without the idea
	 * that was chosen to be merged with (not to merge with the same idea)
	 * 
	 * @author Aly Mostafa
	 * @version 2011.0502
	 * @param two idea ids,
	 *            , id of the topic or entity or organization it belongs to ,
	 *            string belonger type
	 */

	public static void merge(long idea, long belonger, String var) {

		Idea idea1 = Idea.findById(idea);

		List x;
		if (var.equalsIgnoreCase("topic")) {
			x = idea1.getTopic().getIdeas();

		}

		else if (var.equalsIgnoreCase("entity")) {
			x = idea1.getEntity().getIdeas();

		} else {
			x = idea1.getOrganization().getIdeas();
		}
		x.remove(Idea.findById(idea));
		
		if(x.isEmpty())
			error("No Other ideas to merge with ");
		else
		render(x, idea, belonger, var);
	}

	/**
	 * sends a request for merging 2 ideas
	 * 
	 * @author Aly Mostafa
	 * @version 2011.0502
	 * @param two idea ids,
	 *            , id of the topic or entity or organization it belongs to ,
	 *            string belonger type
	 *            
	 * @throws EmailException
	 */
	
	public static void mergeRequestSent(long id1, long id2, long belonger,
			String var) throws EmailException {

		LinkedList<User> reciever = new LinkedList<User>();
		if (var.equalsIgnoreCase("topic")) {

			Topic t = Topic.findById(belonger);

			reciever.add(t.getInitiator());
		}

		else if (var.equalsIgnoreCase("entity")) {
			Eentity e = Eentity.findById(belonger);
			reciever = e.getOrganizers();
		} else {

			Organization o = Organization.findById(belonger);
			reciever = o.getOrganizers();
		}

		int i = 0;
		String username = session.get("username");
		User s = (User) User.find("byUsername", username).fetch().get(0);

		while (i < reciever.size()) {

			Users.sendRequest(s, reciever.get(i), "Merge", id1 + "-" + id2
					+ "-" + belonger + "-" + var, false);
	
			i++;
		}
		render();
	}

	/**
	 * promotes idea to execution
	 * 
	 * @author YoussefSelim
	 * @version 2011.0503
	 * @category C5S13
	 * @param ideaID
	 *            : The ID of the idea which will be promoted
	 */
	public static void promoteToExecution(long ideaID) {
		Idea idea = Idea.findById(ideaID);
		if (idea == null)
			error("The idea doesn't exist !");

		Organization org = idea.getOrganization();
		String username = Security.connected();
		User user = User.find("byUsername", username).first();
		boolean flag = false; // check if the user is an idea developer in the same organization

		for (int i = 0; i < user.getRoleList().size(); i++) {

			if (user.getRoleList().get(i).getTitle().equalsIgnoreCase("Ideas' Developer")
					&& user.getRoleList().get(i).getRelatedOrganization() == org)
				flag = true;
		}
		if (flag == false)
			error("You don't have the permission for this action !");

		idea.setExecutionStatus(true);
		idea.save();
		redirect("/application/success");
	}

	/**
	 * @author Nader Alexan
	 * @version 2011.0505
	 * @category extra
	 * @param
	 * @return void
	 */
	public static void createIdeaN(String title, String ideaDetail,
			boolean isDraft) {
		Topic t = new Topic();
		t.save();
		String username = session.get("username");
		User user = User.findByUsername(username);
		LinkedList<User> creators = new LinkedList<User>();
		creators.add(user);
		Idea idea = new Idea(title, ideaDetail, isDraft, t, creators);
		idea.save();
		long id = idea.getId();
		System.out.println(id);
		render(id);
	}
}
